const getProperty = (target, key?) => {
    return target[key]
}

console.log(9999, getProperty('zhen'))
console.log(9999, getProperty(123))

const swap = <T, U>(arr: [T, U]):[U, T] => {
    return [arr[1], arr[0]]
}
console.log('交换元素1', swap(['zhen', 123]))
console.log('交换元素2', swap([1212, true]))

// 函数内部使用范型变量的时候，如果要操作某些属性或方法 要用范型约束（extends）
// 使用extends约束范型T必须符合接口ILengthwise的定义
interface ILengthwise {
    length: number
}
const loggingIdentity = <T extends ILengthwise>(arg: T): T => {
    console.log('length=', arg.length)
    return arg
}

console.log('范型约束1', loggingIdentity([1,2,3]))

// 多个类型之间互相约束
const copyFileds = <T extends U, U>(target: T, source: U): T => {
    for(let i in source) {
        target[i] = (<T>source)[i]
    }
    return target

}
const tt = { a: 1, b: 2, c: 3, d: 4}
const ss = {b: 20, d: 40}
console.log('多个类型间相互约束', copyFileds(tt, ss))

interface SearchFunc {
    (source: string, subString: string): boolean
}
let mySearch: SearchFunc
mySearch = (source: string, subString: string) => {
    console.log(source.search(subString))
    return source.search(subString) !== -1
}
console.log('范型接口1', mySearch('hen123zhen', 'zhen2'))

interface ICreateArrayFun {
    <T>(length: number, v: T): Array<T>
}
let CreateArrayFunc = <T>(length: number, v: T): Array<T> => {
    let res: T[] = []
    for (let i = 0; i < length; i++) {
        res.push(v)
    }
    return res
}
console.log('含有范型的接口定义函数的形状',CreateArrayFunc(5, 'zhen') )

// 极课
interface ICourse2 {
    name: string
    price: number[]
    likeHuman: string
    isVip: boolean
}

let course1: ICourse2 = {
    name: 'vue3',
    price: [12, 30],
    likeHuman: '前端小开发',
    isVip: true
}
// type K2 = typeof course1
// type K1 = keyof ICourse
const getProperty2 = <T, K extends keyof T>(target: T, key: K): T[K] => {
    return target[key]

}
console.log(getProperty2(course1, 'name'))
// console.log(getProperty2(course1, 'name1'))
// let course2: K1 = {
//     name: 123,
//     price: [12, 30],
//     likeHuman: '前端小开发',
//     isVip: true
// }
// const getProperty3 = <T, K >(target: T, key: K): T[K] => {
//     return target[key]

// }
// console.log(getProperty2(course1, 'name'))
